package com.hllxd.hism.star.basic.service.config.influxdb;

import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.Point;
import org.influxdb.dto.Point.Builder;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * author: xiyong.lxy
 * date: 2018-11-28 9:13
 */
@Slf4j
public class InfluxDBConnect {

    /** 用户名 */
    private String username;
    /** 密码 */
    private String password;
    /** 连接地址 */
    private String openurl;
    /** 数据库 */
    private String database;

    private static final String TBL_COUNTER_DELAY = "bcp_counter_delay";
    private static final String TBL_COUNTER_TS = "bcp_counter_ts";

    private InfluxDB influxDB;

    public InfluxDBConnect(String username, String password, String openurl, String database) {
        this.username = username;
        this.password = password;
        this.openurl = openurl;
        this.database = database;
    }

    /** 连接时序数据库；获得InfluxDB **/
    public InfluxDB influxDbBuild() {
        if (influxDB == null) {
            influxDB = InfluxDBFactory.connect(openurl, username, password);
            //influxDB.createDatabase(database);
        }
        return influxDB;
    }
    /**
     * 设置数据保存策略 defalut 策略名 /database 数据库名/ 30d 数据保存时限30天/ 1 副本个数为1/ 结尾DEFAULT
     * 表示 设为默认的策略
     */
    public void createRetentionPolicy() {
        String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
            "defalut", database, "30d", 1);
        this.query(command);
    }

    /**
     * 查询
     *
     * @param command
     *      查询语句
     * @return
     */
    public List<QueryResult.Result> query(String command) {
        QueryResult results = influxDB.query(new Query(command, database));
        if(results.getResults() == null){
            return null;
        }
        return results.getResults();
    }

    // 通过指定db读取数据
    public List<QueryResult.Result> query(String command, String db) {
        log.info("db: {}, command: {}.",db, command);
        QueryResult results = influxDB.query(new Query(command, db));
        if(results.getResults() == null){
            return null;
        }
        return results.getResults();
    }

    /**
     * 插入
     *
     * @param measurement
     *      表
     * @param tags
     *      标签
     * @param fields
     *      字段
     */
    public void insert(String measurement, Map<String, String> tags, Map<String, Object> fields) {
        Builder builder = Point.measurement(measurement);
        builder.time(((long)fields.get("currentTime"))*1000000, TimeUnit.NANOSECONDS);
        builder.tag(tags);
        builder.fields(fields);
        //
        influxDB.write(database, "", builder.build());
    }

//    public void batchInsertTs2(
//        Map<String,Map<FilterEntity,Counter>> count, String tblName) {
//        if(count.size()<1) return;
//
//        BatchPoints batchPoints = BatchPoints.database(this.database)
//            .consistency(InfluxDB.ConsistencyLevel.ALL)
//            .build();
//        for( Map.Entry<String,Map<FilterEntity,Counter>> iter: count.entrySet()) {
//            String rk = iter.getKey();
//            Map<FilterEntity,Counter> value = iter.getValue();
//            if(value.size()<1) continue;
//            long ts = getTimestamp(rk);
//            log.info("batchInsertTs {}-{}", rk, ts);
//            Point.Builder point = Point.measurement(tblName).time(ts, TimeUnit.MILLISECONDS);
//            Map<String,Counter> tsCounter = new HashMap<>();
//            for(Map.Entry<FilterEntity,Counter> it: value.entrySet()) {
//                FilterEntity en = it.getKey();
//                Counter c = it.getValue();
//                String key = String.format("%s:%s",en.statusCode,en.idcCode);
//                point.addField(key, c.count);
//                addCounter(tsCounter,en.statusCode,c.count);
//            }
//            // 添加对应的状态
//            for(Map.Entry<String,Counter> it: tsCounter.entrySet()) {
//                String status = it.getKey();
//                Counter counter = it.getValue();
//                point.addField(status, counter.count);
//            }
//            batchPoints.point(point.build());
//        }
//        influxDB.write(batchPoints);
//    }
    private String getPrimaryBizCode(String bizCode) {
        if(bizCode==null) {
            return null;
        }
        String[] items = bizCode.split("\\^");
        //if(items.length !=2) return null;
        return items[0];
    }

//    public void batchInsertTsBiz2(
//        Map<String,Map<FilterEntity,Counter>> count, String tblName) {
//        if(count.size()<1) return;
//
//        BatchPoints batchPoints = BatchPoints.database(this.database)
//            .consistency(InfluxDB.ConsistencyLevel.ALL)
//            .build();
//        for( Map.Entry<String,Map<FilterEntity,Counter>> iter: count.entrySet()) {
//            String rk = iter.getKey();
//            Map<FilterEntity,Counter> value = iter.getValue();
//            if(value.size()<1) continue;
//            long ts = getTimestamp(rk);
//            log.info("batchInsertTs {}-{}", rk, ts);
//            Map<String,Counter> bizCounter = new HashMap<>();
//            Point.Builder point = Point.measurement(tblName).time(ts, TimeUnit.MILLISECONDS);
//            for(Map.Entry<FilterEntity,Counter> it: value.entrySet()) {
//                FilterEntity en = it.getKey();
//                Counter c = it.getValue();
//                String key = String.format("%s:%s:%s",en.bizCode,en.statusCode,en.idcCode);
//                point.addField(key, c.count);
//
//                String primBizCode = getPrimaryBizCode(en.bizCode);
//                if(primBizCode==null) {
//                    log.warn("bizCode is invalid.{}",en.bizCode);
//                    continue;
//                }
//                String bizStatus = String.format("%s:%s",primBizCode,en.statusCode);
//                addCounter(bizCounter, bizStatus, c.count);
//            }
//            for(Map.Entry<String,Counter> it: bizCounter.entrySet()) {
//                String biz = it.getKey();
//                Counter counter = it.getValue();
//                log.info("{}, {}", biz,counter.count);
//                point.addField(biz, counter.count);
//            }
//            batchPoints.point(point.build());
//        }
//        influxDB.write(batchPoints);
//    }

//    public void batchInsertTsShop2(
//        Map<String,Map<FilterEntity,Counter>> count, String tblName) {
//        log.info("batchInsertTsShop2 don't insert data.");
//    }

    /**
     * 删除
     *
     * @param command
     *      删除语句
     * @return 返回错误信息
     */
    public String deleteMeasurementData(String command) {
        QueryResult result = influxDB.query(new Query(command, database));
        return result.getError();
    }
}
